﻿#ifndef __INC_QG_BLITS_H__
#define __INC_QG_BLITS_H__

#ifdef _MSC_VER
#pragma once
#endif

//////////////////////////////////////////////////////////////////////////
// 블릿

//
enum qgBlitOp
{
	QG_BLITOP_NONE,
	QG_BLITOP_COLOR,
	QG_BLITOP_ALPHA_COLOR,
	QG_BLITOP_TEX,
	QG_BLITOP_TEX_ALPHA,
	QG_BLITOP_TEX_ALPHA_COLOR,
};

//
enum qgBlitClip
{
	QG_BLITCLIP_NONE=0,
	QG_BLITCLIP_LEFT=1,
	QG_BLITCLIP_TOP=2,
	QG_BLITCLIP_RIGHT=4,
	QG_BLITCLIP_BOTTOM=8,
};

// 이미지에 블릿
namespace qgBlitImage
{
	bool Blit(qgBlitOp op, qgImage* dst, const tpl::Rect* drect, const tpl::Point& dpos, qgImage* src, const tpl::Rect* srect, const tpl::ColorValue& argb);
	bool StrechBlit(qgBlitOp op, qgImage* dst, const tpl::Rect* drect, qgImage* src, const tpl::Rect* srect, const tpl::ColorValue& argb);

	void DrawRect(qgImage* img, const tpl::Rect& rt, const tpl::ColorValue& cc);
	void DrawLine(qgImage* img, const tpl::Point& start, const tpl::Point& end, const tpl::ColorValue& cc);
}

// 블짓 작업
namespace qgBlitWork
{
	void ColorConvert(kconstpointer sp, qgColorFormat sf, kint sn, kpointer dp, qgColorFormat df);
	
	qgBlitClip GetClip(const tpl::Rect& r, const tpl::Point& p);
	tpl::Rect BuildClip(const tpl::Rect* clip, qgImage* img, bool passnative);
	tpl::Rect MakeClip(qgImage* img);
	kint ClipLine(const tpl::Rect& clip, tpl::Point* p0, tpl::Point* p1, const tpl::Point& in0, const tpl::Point& in1);
	
	kuint ExtractAlpha(kuint c);
	kuint PackAlpha(kuint c);
	
	kuint PixelLerp(kuint s, kuint v);
	kuint PixelBlend(kuint c2, kuint c1, kuint alpha);
	kuint PixelInvBlend(kuint c2, kuint c1);
	kushort PixelBlend16(kushort c2, kuint c1, kushort alpha);
}

// 복사
namespace qgBlitCopy
{
	// WARNING: the 'pitch' is not byte length. depend on type of 'out'
	void COPY_1_16(kint width, kint height, const kbyte* in, int linepad, kushort* out, kint pitch, bool flip);
	void COPY_1_32(kint width, kint height, const kbyte* in, int linepad, kint* out, kint pitch, bool flip);
	void COPY_4_16(kint width, kint height, const kbyte* in, int linepad, kushort* out, kint pitch, const kint* palette, bool flip);
	void COPY_8_16(kint width, kint height, const kbyte* in, int linepad, kshort* out, kint pitch, const kint* palette, bool flip);
	void COPY_16_16(kint width, kint height, const kshort* in, int linepad, kshort* out, kint pitch, bool flip);
	void COPY_16_32(kint width, kint height, const kshort* in, int linepad, kint* out, kint pitch, bool flip);
	void COPY_24_32(kint width, kint height, const kbyte* in, int linepad, kint* out, kint pitch, bool flip);
	void COPY_32_32(kint width, kint height, const kint* in, int linepad, kint* out, kint pitch, bool flip);
	void COPY_BGR_4_32(kint width, kint height, const kbyte* in, int linepad, kint* out, kint pitch, const kint* palette, bool flip);
	void COPY_BGR_8_32(kint width, kint height, const kbyte* in, int linepad, kint* out, kint pitch, const kint* palette, bool flip);
	void COPY_BGR_16_32(kint width, kint height, const kshort* in, int linepad, kint* out, kint pitch, bool flip);
	void COPY_BGR_24_32(kint width, kint height, const kbyte* in, int linepad, kint* out, kint pitch, bool flip);
	void COPY_BGR_32_32(kint width, kint height, const kint* in, int linepad, kint* out, kint pitch, bool flip);
}

// 색깔 변환과 처리
namespace qgColorWork
{
	//
	K_INLINE kushort TRN_RGB16_RGBA16(kushort color)
	{
		return 0x8000 | (((color & 0xFFC0) >> 1) | (color & 0x1F));
	}

	K_INLINE kuint TRN_RGB16_RGBA32(kushort color)
	{
		return 0xFF000000 |
			((color & 0xF800) << 8) | ((color & 0x07E0) << 5) | ((color & 0x001F) << 3);
	}

	K_INLINE kuint TRN_RGB16_BGRA32(kushort color)
	{
		return 0xFF000000 |
			((color & 0xF800) >> 8) | ((color & 0x07E0) << 5) | ((color & 0x001F) << 19);
	}

	//
	K_INLINE kushort TRN_RGBA16_RGB16(kushort color)
	{
		return ((color & 0x7FE0) << 1) | (color & 0x1F);
	}

	K_INLINE kuint TRN_RGBA16_RGBA32(kushort color)
	{
		return (((-((kint)color & 0x00008000) >> (kint)31) & 0xFF000000) |
			((color & 0x00007C00) << 9) | ((color & 0x00007000) << 4) |
			((color & 0x000003E0) << 6) | ((color & 0x00000380) << 1) |
			((color & 0x0000001F) << 3) | ((color & 0x0000001C) >> 2));
	}

	K_INLINE kuint TRN_RGBA16_BGRA32(kushort color)
	{
		k_halt_impl("qgCcmWork");
		return 0;
	}

	//
	K_INLINE kushort TRN_RGB32_RGB16(kuint color)
	{
		return (kushort)(
			((color & 0x00F80000) >> 8) |
			((color & 0x0000FC00) >> 5) |
			((color & 0x000000F8) >> 3));
	}

	K_INLINE kushort TRN_RGB32_RGBA16(kuint color)
	{
		return (kushort)(0x8000 |
			((color & 0x00F80000) >> 9) |
			((color & 0x0000F800) >> 6) |
			((color & 0x000000F8) >> 3));
	}

	K_INLINE kuint TRN_RGB32_BGRA32(kuint color)
	{
		kvint& v = (kvint&)color;
		return K_MAKECOLOR(0xFF, v.b.c, v.b.b, v.b.a);
	}

	//
	K_INLINE kushort TRN_RGBA32_RGB16(kuint color)
	{
		return (kushort)(
			((color & 0x00F80000) >> 8) |
			((color & 0x0000FC00) >> 5) |
			((color & 0x000000F8) >> 3));
	}

	K_INLINE kushort TRN_RGBA32_RGBA16(kuint color)
	{
		return (kushort)(
			((color & 0x80000000) >> 16) |
			((color & 0x00F80000) >> 9) |
			((color & 0x0000F800) >> 6) |
			((color & 0x000000F8) >> 3));
	}

	K_INLINE kuint TRN_RGBA32_BGRA32(kuint color)
	{
		kvint v = (kvint&)color;
#if 0
		return K_MAKECOLOR(v.b.d, v.b.c, v.b.b, v.b.a);
#else
		return K_MAKECOLOR(v.b.d, v.b.a, v.b.b, v.b.c);
#endif
	}

	//
	K_INLINE kushort TRN_BGRA32_RGB16(kuint color)
	{
		return (kushort)(
			((color & 0x000000F8) << 8) |
			((color & 0x0000FC00) >> 5) |
			((color & 0x00F80000) >> 19));
	}

	K_INLINE kushort TRN_BGRA32_RGBA16(kuint color)
	{
		return (kushort)(
			((color & 0x80000000) >> 16) |
			((color & 0x000000F8) << 9) |
			((color & 0x0000F800) >> 6) |
			((color & 0x00F80000) >> 19));
	}

	K_INLINE kuint TRN_BGRA32_RGBA32(kuint color)
	{
		kvint v = (kvint&)color;
		return K_MAKECOLOR(v.b.d, v.b.a, v.b.b, v.b.c);
	}

	//
	K_INLINE kuint GET_RGBA16_A(kushort color)
	{
		return (color >> 15) & 0x1;
	}

	K_INLINE kuint GET_RGBA16_R(kushort color)
	{
		return (color >> 10) & 0x1F;
	}

	K_INLINE kuint GET_RGBA16_G(kushort color)
	{
		return (color >> 5) & 0x1F;
	}

	K_INLINE kuint GET_RGBA16_B(kushort color)
	{
		return color & 0x1F;
	}
}

#endif	// __INC_QG_BLITS_H__
